#include "sai.h"
#include "Peripherals_Instence.h"
#include "MemoryMalloc.h"


#define SAI_Handle_MemoryMalloc                                   MemoryMalloc_DTCM
#define SAI_Peripheral_MemoryMalloc                               MemoryMalloc_D2SRAM



SAI_HandleTypeDef hsai_BlockB2;
DMA_HandleTypeDef hdma_sai2_b;

/* SAI2 init function */
void MX_SAI2_Init(void){


  hsai_BlockB2.Instance = SAI2_Block_B;
  hsai_BlockB2.Init.Protocol = SAI_FREE_PROTOCOL;
  hsai_BlockB2.Init.AudioMode = SAI_MODEMASTER_TX;
  hsai_BlockB2.Init.DataSize = SAI_DATASIZE_32;
  hsai_BlockB2.Init.FirstBit = SAI_FIRSTBIT_MSB;
  hsai_BlockB2.Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
  hsai_BlockB2.Init.Synchro = SAI_ASYNCHRONOUS;
  hsai_BlockB2.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;
  hsai_BlockB2.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;
  hsai_BlockB2.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_EMPTY;
  hsai_BlockB2.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_MCKDIV;
  hsai_BlockB2.Init.Mckdiv = 0;
  hsai_BlockB2.Init.SynchroExt = SAI_SYNCEXT_DISABLE;
  hsai_BlockB2.Init.MonoStereoMode = SAI_STEREOMODE;
  hsai_BlockB2.Init.CompandingMode = SAI_NOCOMPANDING;
  hsai_BlockB2.Init.TriState = SAI_OUTPUT_NOTRELEASED;
  hsai_BlockB2.Init.PdmInit.Activation = DISABLE;
  hsai_BlockB2.Init.PdmInit.MicPairsNbr = 1;
  hsai_BlockB2.Init.PdmInit.ClockEnable = SAI_PDM_CLOCK1_ENABLE;
  hsai_BlockB2.Init.MckOverSampling=SAI_MCK_OVERSAMPLING_DISABLE;
  hsai_BlockB2.FrameInit.FrameLength = 64;
  hsai_BlockB2.FrameInit.ActiveFrameLength = 32;
  hsai_BlockB2.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
  hsai_BlockB2.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
  hsai_BlockB2.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
  hsai_BlockB2.SlotInit.FirstBitOffset = 0;
  hsai_BlockB2.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
  hsai_BlockB2.SlotInit.SlotNumber = 2;
  hsai_BlockB2.SlotInit.SlotActive = 0x00000003;
  if (HAL_SAI_Init(&hsai_BlockB2) != HAL_OK)
  {
    Error_Handler();
  }


  ip_sai2_b=SAI_Handle_MemoryMalloc.Malloc(sizeof(IP_SAI_Block));
  ip_sai2_b_dma=SAI_Handle_MemoryMalloc.Malloc(sizeof(IP_DMA));

  if(cH_IsNull(ip_sai2_b)||cH_IsNull(ip_sai2_b_dma)){
    for(;;){
    }
  }

  IP_DMA_Init(ip_sai2_b_dma,hsai_BlockB2.hdmatx->Instance);
  IP_SAI_MasterTx_Init(ip_sai2_b,ip_sai2_b_dma,hsai_BlockB2.Instance);

}

void MX_SAI2_DeInit(){

  HAL_SAI_DeInit(&hsai_BlockB2);
  SAI_Handle_MemoryMalloc.Free(ip_sai2_b);
  SAI_Handle_MemoryMalloc.Free(ip_sai2_b_dma);
  ip_sai2_b=NULL;

}

static uint32_t SAI2_client =0;

void HAL_SAI_MspInit(SAI_HandleTypeDef* hsai)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  
  /* SAI2 */
  if(hsai->Instance==SAI2_Block_B)
  {
    /* SAI2 clock enable */

    if (SAI2_client == 0)
    {
      __HAL_RCC_SAI2_CLK_ENABLE();
    }
    SAI2_client++;

    
    RCC->AHB4ENR|=RCC_AHB4ENR_GPIOEEN;

    /**SAI2_B_Block_B GPIO Configuration
    PE11     ------> SAI2_SD_B
    PE12     ------> SAI2_SCK_B
    PE13     ------> SAI2_FS_B
    PE14     ------> SAI2_MCLK_B
    */
    GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF10_SAI2;
    HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_13;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
    GPIO_InitStruct.Alternate = GPIO_AF10_SAI2;
    HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_14;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF10_SAI2;
    HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

    /* Peripheral DMA init*/

    hdma_sai2_b.Instance = DMA1_Stream7;
    hdma_sai2_b.Init.Request = DMA_REQUEST_SAI2_B;
    hdma_sai2_b.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_sai2_b.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_sai2_b.Init.MemInc = DMA_MINC_ENABLE;
    hdma_sai2_b.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    hdma_sai2_b.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
    hdma_sai2_b.Init.Mode = DMA_NORMAL;
    hdma_sai2_b.Init.Priority = DMA_PRIORITY_LOW;
    hdma_sai2_b.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    hdma_sai2_b.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
    hdma_sai2_b.Init.MemBurst = DMA_MBURST_INC4;
    hdma_sai2_b.Init.PeriphBurst = DMA_PBURST_SINGLE;
    if (HAL_DMA_Init(&hdma_sai2_b) != HAL_OK)
    {
      Error_Handler();
    }

    /* Several peripheral DMA handle pointers point to the same DMA handle.
      Be aware that there is only one channel to perform all the requested DMAs. */
    __HAL_LINKDMA(hsai,hdmarx,hdma_sai2_b);
    __HAL_LINKDMA(hsai,hdmatx,hdma_sai2_b);
  }
}

void HAL_SAI_MspDeInit(SAI_HandleTypeDef* hsai)
{

  /* SAI2 */
  if(hsai->Instance==SAI2_Block_B)
  {
    SAI2_client --;
    if (SAI2_client == 0)
    {
      /* Peripheral clock disable */
      __HAL_RCC_SAI2_CLK_DISABLE();
    }

    /**SAI2_B_Block_B GPIO Configuration
    PE11     ------> SAI2_SD_B
    PE12     ------> SAI2_SCK_B
    PE13     ------> SAI2_FS_B
    PE14     ------> SAI2_MCLK_B
    */
    HAL_GPIO_DeInit(GPIOE, GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14);

    HAL_DMA_DeInit(hsai->hdmarx);
    HAL_DMA_DeInit(hsai->hdmatx);
  }
}



